#pragma once

#include "Quat.h"

/**
* <p>Title: CHAnimJoint </p>
* <p>Description: Internal class for hierarchical calculations of H-Anim joint rotations.</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: CIANT</p>
* @author not attributable
* @version 1.0
*/

/**
* This class represents one H-Anim joint.
*/
class CHAnimJoint {

protected:
  enum {
    MAX_CHILDREN_JOINTS=5
  };

	/// children joints of the joint
  CHAnimJoint* children[MAX_CHILDREN_JOINTS];

  /// number of children joints
  int numberOfChildren;

  /// is calibrated
  bool calibrated;
  
  /// is the joint used
  bool used;

	/// inverse of the calibration rotation
  CQuat invertedCalibrationQ;
	
  /// raw input rotation
  CQuat inputQ;
	
  /// raw input position
  CVector3D inputP;

  /// input rotation multiplied by inversed calibration (inputQ * invertedCalibrationQ)
  CQuat inputQCalibrated;

  /// resulting rotation of the joint
  CQuat outputQ;

  /// resulting position of the joint
  CVector3D outputP;

  /// calibration position
  CVector3D calibrationP;

public:

	/// constructor
  CHAnimJoint() : calibrated(false), numberOfChildren(0) {}
	
	/**
  * Adds a children joint to create hierarchical structure of joints.
  * @param childrenJoint children joint
  */
  void addNode(CHAnimJoint* childrenJoint) {
		children[numberOfChildren++] = childrenJoint;
	}

  /// Set calibration.
  void setCalibration(CQuat calibQ, CVector3D calibP);

  /// Set input raw position and rotation.
  void CHAnimJoint::setInput(CQuat inQ, float inP[]);

  /// Get input rotation multiplied by inversed calibration.
  CQuat getInputQCalibrated() {
		return inputQCalibrated;
	}

	/// Get the resulting position of the joint.
  CVector3D getOutputP() {
		return outputP;
	}

	/// Get the resulting rotation of the joint.
  CQuat getOutputQ() {
		return outputQ;
	}

  /// Activate / deactivate the joint. Should follow setCurrent and setCurrentPos calls.
  void setUsed(bool used) {
		this->used = used;
	}

  /// Is the joint used?
  bool isUsed() {
		return used;
	}

  /// Hierarchical calculation of rotations and positions of the joints.
  void calcOutput(CQuat upper);

};